package cmd

import (
	"bufio"
	"context"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"strings"

	"github.com/kolorbgg/k8scopilot/cmd/utils"
	"github.com/sashabaranov/go-openai"
	"github.com/sashabaranov/go-openai/jsonschema"
	"github.com/spf13/cobra"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/restmapper"
)

var chatgptCmd = &cobra.Command{
	Use:   "chatgpt",
	Short: "K8s Copilot - 一个Kubernetes助手",
	Long:  `K8s Copilot 可以帮助你生成、查询和管理Kubernetes资源`,
	Run: func(cmd *cobra.Command, args []string) {
		startChat()
	},
}

func startChat() {
	scanner := bufio.NewScanner(os.Stdin)
	fmt.Println("我是 K8s Copilot，请输入问题 (输入'exit'退出):")
	for {
		fmt.Print("> ")
		if !scanner.Scan() {
			break
		}

		input := scanner.Text()
		if input == "exit" {
			fmt.Println("退出程序")
			break
		} else if input == "" {
			continue
		}

		response := processInput(input)
		fmt.Println(response)
	}
}

func processInput(input string) string {
	client, err := utils.NewDeepSeekClient()
	if err != nil {
		log.Fatalf("Failed to create DeepSeek client: %v", err)
	}

	return handleFunctionCalling(input, client)
}

func handleFunctionCalling(input string, client *utils.DeepSeekClient) string {
	// 定义可用的工具函数
	tools := []openai.Tool{
		{
			Type: openai.ToolTypeFunction,
			Function: &openai.FunctionDefinition{
				Name:        "generate_k8s_yaml",
				Description: "生成K8s yaml内容",
				Parameters: jsonschema.Definition{
					Type: jsonschema.Object,
					Properties: map[string]jsonschema.Definition{
						"resource_type": {
							Type:        jsonschema.String,
							Description: "K8s资源类型，如Deployment、Service等",
						},
						"image": {
							Type:        jsonschema.String,
							Description: "容器镜像",
						},
						"replicas": {
							Type:        jsonschema.Integer,
							Description: "副本数量",
						},
					},
					Required: []string{"resource_type", "image"},
				},
			},
		},
		{
			Type: openai.ToolTypeFunction,
			Function: &openai.FunctionDefinition{
				Name:        "query_k8s_resources",
				Description: "查询K8s资源",
				Parameters: jsonschema.Definition{
					Type: jsonschema.Object,
					Properties: map[string]jsonschema.Definition{
						"namespace": {
							Type:        jsonschema.String,
							Description: "命名空间",
						},
						"resource_type": {
							Type:        jsonschema.String,
							Description: "资源类型，如Pod、Deployment等",
						},
					},
					Required: []string{"namespace", "resource_type"},
				},
			},
		},
		{
			Type: openai.ToolTypeFunction,
			Function: &openai.FunctionDefinition{
				Name:        "delete_k8s_resources",
				Description: "删除K8s资源",
				Parameters: jsonschema.Definition{
					Type: jsonschema.Object,
					Properties: map[string]jsonschema.Definition{
						"namespace": {
							Type:        jsonschema.String,
							Description: "命名空间",
						},
						"resource_type": {
							Type:        jsonschema.String,
							Description: "资源类型",
						},
						"resource_name": {
							Type:        jsonschema.String,
							Description: "资源名称",
						},
					},
					Required: []string{"namespace", "resource_type", "resource_name"},
				},
			},
		},
	}

	// 创建聊天请求
	resp, err := client.Client.CreateChatCompletion(
		context.Background(),
		openai.ChatCompletionRequest{
			Model: "deepseek-chat",
			Messages: []openai.ChatCompletionMessage{
				{
					Role:    openai.ChatMessageRoleSystem,
					Content: "你是一个专业的Kubernetes助手，可以帮助用户生成、查询和管理K8s资源。",
				},
				{
					Role:    openai.ChatMessageRoleUser,
					Content: input,
				},
			},
			Tools: tools,
		},
	)
	if err != nil {
		return fmt.Sprintf("调用DeepSeek API出错: %v", err)
	}

	if len(resp.Choices) == 0 {
		return "未收到有效响应"
	}

	msg := resp.Choices[0].Message

	// 检查是否有函数调用
	if len(msg.ToolCalls) > 0 {
		toolCall := msg.ToolCalls[0]
		switch toolCall.Function.Name {
		case "generate_k8s_yaml":
			var params struct {
				ResourceType string `json:"resource_type"`
				Image        string `json:"image"`
				Replicas     int    `json:"replicas"`
			}
			if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &params); err != nil {
				return fmt.Sprintf("解析参数失败: %v", err)
			}
			// return fmt.Sprintf("将为您生成 %s YAML，使用镜像 %s，副本数 %d", params.ResourceType, params.Image, params.Replicas)
			result, err := callFunction(client, msg.ToolCalls[0].Function.Name, msg.ToolCalls[0].Function.Arguments)
			if err != nil {
				return err.Error()
			}
			return result

		case "query_k8s_resources":
			var params struct {
				Namespace    string `json:"namespace"`
				ResourceType string `json:"resource_type"`
			}
			if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &params); err != nil {
				return fmt.Sprintf("解析参数失败: %v", err)
			}
			// return fmt.Sprintf("将查询命名空间 %s 中的 %s 资源", params.Namespace, params.ResourceType)
			// 调用 callFunction 执行实际查询
			result, err := callFunction(client, msg.ToolCalls[0].Function.Name, msg.ToolCalls[0].Function.Arguments)
			if err != nil {
				return err.Error()
			}
			return result

		case "delete_k8s_resources":
			var params struct {
				Namespace    string `json:"namespace"`
				ResourceType string `json:"resource_type"`
				ResourceName string `json:"resource_name"`
			}
			if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &params); err != nil {
				return fmt.Sprintf("解析参数失败: %v", err)
			}
			return fmt.Sprintf("将删除命名空间 %s 中的 %s %s", params.Namespace, params.ResourceType, params.ResourceName)

		default:
			return fmt.Sprintf("未知的工具调用: %s", toolCall.Function.Name)
		}
	}

	// 如果没有函数调用，直接返回AI的回复
	return msg.Content
}

func callFunction(client *utils.DeepSeekClient, name, arguments string) (string, error) {
	if name == "generate_k8s_yaml" {
		var params struct {
			ResourceType string `json:"resource_type"`
			Image        string `json:"image"`
			Replicas     int    `json:"replicas"`
		}
		if err := json.Unmarshal([]byte(arguments), &params); err != nil {
			return "", fmt.Errorf("解析参数失败: %v", err)
		}

		// 直接传递原始用户输入 + 核心参数（避免二次解析）
		userInput := fmt.Sprintf(
			"生成一个 %s YAML，使用镜像 %s，副本数 %d。其他要求：%s",
			params.ResourceType,
			params.Image,
			params.Replicas,
			arguments, // 保留原始参数（包含未提取的字段如端口、CPU等）
		)
		return generate_k8s_yaml(client, userInput)
	}

	if name == "query_k8s_resources" {
		params := struct {
			Namespace    string `json:"namespace"`
			ResourceType string `json:"resource_type"`
		}{}
		if err := json.Unmarshal([]byte(arguments), &params); err != nil {
			return "", fmt.Errorf("解析参数失败: %w", err)
		}
		return query_k8s_resources(params.Namespace, params.ResourceType)
	}

	return "", fmt.Errorf("未知的工具调用: %s", name)
}

// func generate_k8s_yaml(client *utils.DeepSeekClient, userInput string) (string, error) {
// 	prompt := fmt.Sprintf(`
//         你是一个Kubernetes专家，请根据以下要求生成准确的YAML配置：
//         - 用户需求: %s
//         - 要求:
//             1. 只输出YAML内容，不要包含任何解释或Markdown代码块。
//             2. 确保字段缩进正确。
//             3. 自动补充缺失的合理默认值（如名称、标签等）。
//     `, userInput)

// 	yamlContent, err := client.SendMessage(prompt)
// 	if err != nil {
// 		return "", err
// 	}
// 	return yamlContent, nil
// }

func generate_k8s_yaml(client *utils.DeepSeekClient, userInput string) (string, error) {
	prompt := fmt.Sprintf(`
        你是一个Kubernetes专家，请根据以下要求生成准确的YAML配置：
        - 用户需求: %s
        - 要求:
            1. 只输出YAML内容，不要包含任何解释或Markdown代码块。
            2. 确保字段缩进正确。
            3. 自动补充缺失的合理默认值（如名称、标签等）。
    `, userInput)

	yamlContent, err := client.SendMessage(prompt)
	if err != nil {
		return "", err
	}

	clientGo, err := utils.NewClientGo(kubeconfig)
	if err != nil {
		return "", err
	}
	resources, err := restmapper.GetAPIGroupResources(clientGo.DiscoveryClient)
	if err != nil {
		return "", err
	}
	// 把 YAML 转成 Unstructured
	unstructuredObj := &unstructured.Unstructured{}
	_, _, err = scheme.Codecs.UniversalDeserializer().Decode([]byte(yamlContent), nil, unstructuredObj)
	if err != nil {
		return "", err
	}

	// 创建mapper gpk转为gver
	mapper := restmapper.NewDiscoveryRESTMapper(resources)
	// 从 unstructuredObj 中获取 GVK
	gvk := unstructuredObj.GroupVersionKind()
	mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
	if err != nil {
		return "", err
	}

	namespace := unstructuredObj.GetNamespace()
	if namespace == "" {
		namespace = "default"
	}

	_, err = clientGo.DynamicClient.Resource(mapping.Resource).Namespace(namespace).Create(context.Background(), unstructuredObj, metav1.CreateOptions{})
	if err != nil {
		return "", err
	}

	return yamlContent, nil
}

func query_k8s_resources(namespace, resourceType string) (string, error) {
	clientGo, err := utils.NewClientGo(kubeconfig)
	if err != nil {
		return "", err
	}
	// 统一转为小写并处理单复数
	resourceType = strings.ToLower(strings.TrimSuffix(resourceType, "s")) + "s"

	var gvr schema.GroupVersionResource
	switch resourceType {
	case "deployments":
		gvr = schema.GroupVersionResource{
			Group:    "apps",
			Version:  "v1",
			Resource: "deployments",
		}
	case "services":
		gvr = schema.GroupVersionResource{
			Group:    "",
			Version:  "v1",
			Resource: "services",
		}
	case "pods":
		gvr = schema.GroupVersionResource{
			Group:    "",
			Version:  "v1",
			Resource: "pods",
		}
	default:
		return "", fmt.Errorf("不支持 resource type: %s", resourceType)
	}

	resourceList, err := clientGo.DynamicClient.Resource(gvr).Namespace(namespace).List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		return "", fmt.Errorf("failed to list resources: %w", err)
	}
	result := ""
	for _, item := range resourceList.Items {
		result += fmt.Sprintf("%s: %s\n", resourceType, item.GetName())
	}
	return result, nil
}

func init() {
	askCmd.AddCommand(chatgptCmd)
}
